package app_kvServer;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.log4j.Logger;

import common.messages.MD5Hash;
import common.messages.MetaData;

/**
 * The singleton of each server
 * 
 * @author zhou,shi
 * 
 */
public class Singleton {
	private static Singleton instance;
	private HashMap<String, String> kvmap;
	private boolean writeLock;
	private boolean isStarted;
	private List<MetaData> mList;
	private String start_index;
	private String end_index;
	private static final String TAIL = "ffffffffffffffffffffffffffffffff";
	private static final String HEAD = "00000000000000000000000000000000";
	private Logger logger = Logger.getRootLogger();

	private Singleton() {
		this.kvmap = new HashMap<String, String>();
		this.writeLock = false;
		this.isStarted = false;
		this.mList = new ArrayList<MetaData>();
	}

	/**
	 * check if the key is on current server
	 * 
	 * @param key
	 * @param port
	 * @return if the key is on current server
	 */
	public boolean inRange(String key, int port) {
		for (MetaData m : mList) {
			if (m.getPort().equals(String.valueOf(port))) {
				instance.setStart_index(m.getHead());
				instance.setEnd_index(m.getTail());
			}
		}
		String hashKey = new MD5Hash().doHash(key);
		if (start_index.compareToIgnoreCase(end_index) < 0) {
			if (hashKey.compareToIgnoreCase(start_index) > 0
					&& hashKey.compareToIgnoreCase(end_index) < 0) {
				logger.info(key + " is in range.");
				return true;
			}
		} else {
			if ((hashKey.compareToIgnoreCase(start_index) > 0 && hashKey
					.compareToIgnoreCase(TAIL) < 0)
					|| (hashKey.compareToIgnoreCase(HEAD) > 0 && hashKey
							.compareToIgnoreCase(end_index) < 0)) {
				logger.info(key + " is in range.");
				return true;
			}
		}
		logger.info(key + " is NOT in range.");
		return false;
	}

	/**
	 * @return instance of singleton
	 */
	public static Singleton getInstance() {
		if (instance == null) {
			synchronized (Singleton.class) {
				instance = new Singleton();
			}
		}
		return instance;
	}

	public HashMap<String, String> getKvmap() {
		return kvmap;
	}

	public void setKvmap(HashMap<String, String> kvmap) {
		this.kvmap = kvmap;
	}

	public boolean isWriteLock() {
		return writeLock;
	}

	public void setWriteLock(boolean writeLock) {
		this.writeLock = writeLock;
	}

	public boolean isStarted() {
		return isStarted;
	}

	public void setStarted(boolean isStarted) {
		this.isStarted = isStarted;
	}

	public List<MetaData> getmList() {
		return mList;
	}

	public void setmList(List<MetaData> mList) {
		this.mList = mList;
	}

	public String getStart_index() {
		return start_index;
	}

	public void setStart_index(String start_index) {
		this.start_index = start_index;
	}

	public String getEnd_index() {
		return end_index;
	}

	public void setEnd_index(String end_index) {
		this.end_index = end_index;
	}

}
